﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TD.bom
{
    /// <summary>
    /// Template d'une carte, i.e. ensemble d'éléments permettant de créer une carte
    /// </summary>
    public class MapTemplate : TemplateBase
    {
        #region Type(s) interne(s) 
        
        /// <summary>
        /// Données d'une vague de monstres
        /// </summary>
        public struct WaveData
        {
            /// <summary>
            /// Nombre total de monstres pour cette vague
            /// </summary>
            public int TotalMonsterCount;

            /// <summary>
            /// Nom du template du monstre de la vague 
            /// </summary>
            public string MonsterTemplateName; // TODO : permettre un panachage de monstres

            /// <summary>
            /// Nb de ms entre 2 arrivées de monstre dans cette vague 
            /// </summary>
            public uint MonsterOutputPeriod;
        }

        #endregion

        #region Propriétés

        /// <summary>
        /// Templates des cases
        /// </summary>
        public string[,] CaseTemplateNames { get; private set; }

        /// <summary>
        /// Taille en pixel d'une case
        /// </summary>
        public MapObjectSize CaseSize { get; private set; }

        /// <summary>
        /// Points de passage de la carte
        /// </summary>
        public Point[] WayPoints { get; private set; } // TODO : gérer des chemins multiples

        /// <summary>
        /// Template des tours disponibles
        /// </summary>
        public string[] TowerTemplateNames { get; private set; }

        /// <summary>
        /// Templates de vagues sur cette carte
        /// </summary>
        public WaveData[] WavesData { get; private set; }

        #endregion

        /// <summary>
        /// Obtient un template de carte
        /// </summary>
        /// <param name="p_templateName">Nom du template</param>
        /// <returns>Instance de MapTemplate si trouvé, null sinon</returns>
        public new static MapTemplate Get(string p_templateName)
        {
            // On regarde d'abord si le template existe en cache
            MapTemplate l_template = (MapTemplate)TemplateBase.Get(p_templateName);
            if (l_template != null)
            {
                // Si oui, on le renvoie
                return l_template;
            }

            // Sinon, il faut le charger
            l_template = Load(p_templateName);
            if (l_template != null)
            {
                // Et le mettre en cache pour la prochaine fois
                m_cache.Add(p_templateName, l_template); 
            }

            return l_template;
        }

        /// <summary>
        /// Charge le template ayant le nom spécifié
        /// </summary>
        /// <param name="p_templateName">Nom du template à charger</param>
        /// <returns>Instance de MapTemplate si trouvé, null sinon</returns>
        protected static MapTemplate Load(string p_templateName)
        {
            // TODO : implémenter un chargement à partir d'un entrepôt quelconque
            // serveur (par service web), ressources...
            MapTemplate l_template = new MapTemplate();

            switch(p_templateName)
            {
                case "map/1":
                    {
                        // Les cases de la carte
                        l_template.CaseTemplateNames = new string[,] {
                            {"case/1", "case/2", "case/2"},
                            {"case/1", "case/1", "case/1"},
                            {"case/2", "case/2", "case/1"}
                            };

                        // Leur taille
                        l_template.CaseSize = new MapObjectSize { Height = 50, Width = 50 };

                        // Les points de passage
                        l_template.WayPoints = new Point[] { new Point(0, 0), new Point(0, 1), new Point(2, 1), new Point(2, 2) };

                        // Les tours disponibles
                        l_template.TowerTemplateNames = new string[] { "tower/1", "tower/2" };

                        // Les vagues de monstres
                        l_template.WavesData = new WaveData[2];
                        
                        // Vague 1
                        l_template.WavesData[0].TotalMonsterCount = 5;
                        l_template.WavesData[0].MonsterTemplateName = "monster/1";
                        l_template.WavesData[0].MonsterOutputPeriod = 1000;

                        // Vague 2
                        l_template.WavesData[0].TotalMonsterCount = 5;
                        l_template.WavesData[0].MonsterTemplateName = "monster/2";
                        l_template.WavesData[0].MonsterOutputPeriod = 500;
                        break;
                    }

                case "map/2":
                    {
                        // Les cases de la carte
                        l_template.CaseTemplateNames = new string[,] {
                            {"case/1", "case/1", "case/1"},
                            {"case/2", "case/2", "case/1"},
                            {"case/2", "case/2", "case/1"},
                            {"case/1", "case/1", "case/1"}
                            };

                        // Leur taille
                        l_template.CaseSize = new MapObjectSize { Height = 40, Width = 50 };

                        // Les points de passage
                        l_template.WayPoints = new Point[] { new Point(0, 0), new Point(2, 0), new Point(2, 3), new Point(0, 3) };

                        // Les tours disponibles
                        l_template.TowerTemplateNames = new string[] { "tower/1", "tower/3" };

                        // Les vagues de monstres
                        l_template.WavesData = new WaveData[1];

                        // Vague 1
                        l_template.WavesData[0].TotalMonsterCount = 3;
                        l_template.WavesData[0].MonsterTemplateName = "monster/2";
                        l_template.WavesData[0].MonsterOutputPeriod = 1000;
                        break;
                    }

                default:
                    {
                        throw new ArgumentOutOfRangeException("Template de carte non trouvé");
                    }
            }

            return l_template;
        }
    }
}
